﻿<link rel="stylesheet" type="text/css" href="JobConfiguration/css/jobExtension" />
<link rel="stylesheet" type="text/css" href="JobConfiguration/css/cron-expression-input" />

<script type="text/javascript" src="JobConfiguration/js/vue"></script>
<script type="text/javascript" src="JobConfiguration/js/axio"></script>
<script type="text/javascript" src="JobConfiguration/js/sweetalert"></script>
<script defer type="text/javascript" src="JobConfiguration/js/page"></script>
<script type="text/javascript" src="JobConfiguration/js/daysjs"></script>
<script type="text/javascript" src="JobConfiguration/js/relativeTime"></script>
<script>dayjs.extend(dayjs_plugin_relativeTime);</script>
<script type="text/javascript" src="JobConfiguration/js/vuejsPaginate"></script>
<script type="text/javascript" src="JobConfiguration/js/cron-expression-input"></script>

<script type="text/x-template" id="modal-template">
    <transition name="modal">
        <div class="modal-mask">
            <div class="modal-wrapper">
                <div class="modal-container">

                    <div class="modal-header">
                        <slot name="header">
                            default header
                        </slot>
                    </div>

                    <div class="modal-body">
                        <slot name="body">
                            default body
                        </slot>
                    </div>

                    <div class="modal-footer">
                        <button class="modal-default-button btn btn-danger pull-left" @click="closeModal">
                            Close
                        </button>
                        <slot name="footer">
                            <button class="modal-default-button btn btn-success" @click="closeModal">
                                Save
                            </button>
                        </slot>
                    </div>
                </div>
            </div>
        </div>
    </transition>
</script>

<div id="app">

    <modal v-if="showModal" @close="closeModal">

        <form slot="body" id="formJob">

            <div class="form-group">
                <label for="jobId">Job Id</label>
                <input type="text" class="form-control" v-model="job.Id" id="jobId" name="jobId" aria-describedby="emailHelp" placeholder="Enter Job Id">
            </div>
            <div class="form-group">
                <label for="cron">Cron</label>
                <cron-expression-input :value="job.Cron" v-on:input="job.Cron = $event.detail.value" color="d58512" />
            </div>

            <div class="form-group">
                <label for="cron">Time Zone</label>
                <select id="timezoneid" class="form-control" v-model="job.TimeZoneId" name="cron" placeholder="Enter the Time Zone">
                    <option v-for="(item, index) in timeZones" :key="index" :value="item.Item1">{{item.Item2}}</option>
                </select>
            </div>

            <div class="form-group">
                <label for="class">Class</label>
                <input type="text" class="form-control" v-model="job.Class" name="class" aria-describedby="class" id="class" placeholder="Enter Class Name">
                <small id="class" class="form-text text-muted">Please provider path complete about your class example: Hangfire.RecurringJob.MyClass</small>
            </div>

            <div class="form-group">
                <label for="method">Method</label>
                <input type="text" class="form-control" v-model="job.Method" id="method" name="method" placeholder="Enter Method Name">
            </div>

            <div class="form-group">
                <label for="queue">Queue</label>
                <input type="text" class="form-control" v-model="job.Queue" name="queue" id="queue" placeholder="Enter Queue Name">
            </div>

            <div class="form-group">
                <p v-if="errors.length> 0">
                    <b style="color:red">Please correct the following error(s):</b>
                    <ul>
                        <li v-for="error in errors" style="color:red">{{ error }}</li>
                    </ul>
                </p>
            </div>
        </form>

        <div slot="footer">
            <button class="btn btn-success" @click="addJob">
                Save
            </button>
        </div>

        <h3 slot="header">{{title}}</h3>
    </modal>

    <div class="row">
        <div class="col-md-12" style="margin-top: 30px">
            <h1 class="page-header">Recurring Jobs <span class="badge badge-warning">{{getItems.length}}</span></h1>
            <button type="button" class="btn btn-primary" style="margin-bottom: 20px;" @click="OpenModal">Add new Job</button>
            <div class="table-responsive">
                <table class="table">

                    <thead>
                        <tr>
                            <th>Id</th>
                            <th>Cron</th>
                            <th>Queue</th>
                            <th>State</th>
                            <th>Class</th>
                            <th>Method</th>
                            <th>TimeZone</th>
                            <th>Last Execution</th>
                            <th>Next Execution</th>
                            <th>Options</th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr v-for="job in getItems">
                            <td>{{job.Id}}</td>
                            <td>{{job.Cron}}</td>
                            <td>{{job.Queue}}</td>
                            <td>
                                <span v-if="job.JobState == 'Running'" class="label label-success">{{job.JobState}}</span>
                                <span v-if="job.JobState == 'Stopped'" class="label label-danger">{{job.JobState}}</span>
                            </td>
                            <td>{{job.Class}}</td>
                            <td>{{job.Method}}</td>
                            <td>{{job.TimeZoneId}}</td>
                            <td>
                                <button type="button" class="btn btn-primary">
                                    {{getTime(job.LastExecution)}}&nbsp;&nbsp;
                                    <span class="badge" style="width: 124px;">{{capitalizeString(dayjs().from(dayjs(job.LastExecution)))}}</span>
                                </button>
                            </td>
                            <td>
                                <button type="button" class="btn btn-primary">
                                    {{getTime(job.NextExecution)}}&nbsp;&nbsp;
                                    <span class="badge" style="width: 124px;">{{capitalizeString(dayjs().to(dayjs(job.NextExecution)))}}</span>
                                </button>
                            </td>
                            <td>
                                <button type="button" class="btn btn-warning" style="padding-top: 10px; margin-right: 5px;">
                                    <svg width="18px" height="18px" viewBox="0 0 16 16" class="bi bi-pencil-square" fill="currentColor" @click="GetJob(job.Id)">
                                        <path d="M15.502 1.94a.5.5 0 0 1 0 .706L14.459 3.69l-2-2L13.502.646a.5.5 0 0 1 .707 0l1.293 1.293zm-1.75 2.456l-2-2L4.939 9.21a.5.5 0 0 0-.121.196l-.805 2.414a.25.25 0 0 0 .316.316l2.414-.805a.5.5 0 0 0 .196-.12l6.813-6.814z" />
                                        <path fill-rule="evenodd" d="M1 13.5A1.5 1.5 0 0 0 2.5 15h11a1.5 1.5 0 0 0 1.5-1.5v-6a.5.5 0 0 0-1 0v6a.5.5 0 0 1-.5.5h-11a.5.5 0 0 1-.5-.5v-11a.5.5 0 0 1 .5-.5H9a.5.5 0 0 0 0-1H2.5A1.5 1.5 0 0 0 1 2.5v11z" />
                                    </svg>
                                </button>
                                <button v-if="job.JobState == 'Stopped'" type="button" class="btn btn-success" style="padding: 4px 10px;">
                                    <svg width="24px" height="25px" viewBox="-1 -1.5 16 16" class="bi bi-play" fill="currentColor" @click="StartJob(job.Id)">
                                        <path fill-rule="evenodd" d="M10.804 8L5 4.633v6.734L10.804 8zm.792-.696a.802.802 0 0 1 0 1.392l-6.363 3.692C4.713 12.69 4 12.345 4 11.692V4.308c0-.653.713-.998 1.233-.696l6.363 3.692z" />
                                    </svg>
                                </button>
                                <button v-if="job.JobState == 'Running'" type="button" class="btn btn-danger" style="padding: 4px 10px;">
                                    <svg width="24px" height="25px" viewBox="-0.5 -1.5 16 16" class="bi bi-stop" fill="currentColor" @click="StopJob(job.Id)">
                                        <path fill-rule="evenodd" d="M3.5 5A1.5 1.5 0 0 1 5 3.5h6A1.5 1.5 0 0 1 12.5 5v6a1.5 1.5 0 0 1-1.5 1.5H5A1.5 1.5 0 0 1 3.5 11V5zM5 4.5a.5.5 0 0 0-.5.5v6a.5.5 0 0 0 .5.5h6a.5.5 0 0 0 .5-.5V5a.5.5 0 0 0-.5-.5H5z" />
                                    </svg>
                                </button>
                            </td>
                        </tr>
                    </tbody>
                </table>

                <div style="float: right;">
                    <paginate :page-count="getPageCount"
                              :page-range="3"
                              :margin-pages="2"
                              :click-handler="clickCallbackPagination"
                              :prev-text="'＜'"
                              :next-text="'＞'"
                              :container-class="'pagination'"
                              :page-class="'page-item'">
                    </paginate>
                </div>

            </div>
        </div>
    </div>

</div>

<script>
    Vue.component('modal', {
        template: '#modal-template',
        methods: {
            closeModal() {
                this.$emit('close');
            }
        }
    });

    var appJob = new Vue({
        el: '#app',
        components: {
            'paginate': VuejsPaginate
        },
        data() {
            return {
                title: 'Add New Job',
                jobs: null,
                showModal: false,
                errors: [],
                timeZones: [],
                job: {
                    Id: '',
                    Cron: '',
                    Queue: '',
                    TimeZoneId: '',
                    Class: '',
                    Method: '',
                    JobState: ''
                },
                pagination: {
                    parPage: 10,
                    currentPage: 1
                }
            }
        },
        methods: {
            addJob() {
                this.UpdateJob(this.job);
            },
            GetJobs() {
                axios.get('JobConfiguration/GetJobs')
                    .then(res => (this.jobs = res.data))
            },
            GetJob(_Id) {
                this.title = 'Edit Job';
                axios.get('JobConfiguration/GetJob?Id=' + _Id).then(response => {

                    if (response.data != null) {
                        this.showModal = true;
                        this.job.Id = response.data.Object.Id;
                        this.job.Cron = response.data.Object.Cron;
                        this.job.Queue = response.data.Object.Queue;
                        this.job.Class = response.data.Object.Class;
                        this.job.Method = response.data.Object.Method;
                        this.job.TimeZoneId = response.data.Object.TimeZoneId;

                    }
                }).catch(e => {
                    console.log(e);
                });
            },
            StartJob(_jobId) {
                axios.get('JobConfiguration/JobAgent?Id=' + _jobId + "&Action=Start").then(response => {

                    if (!response.data.Status) {

                        this.showModal = false;

                        Swal.fire({
                            title: 'Error!',
                            text: response.data.Message,
                            type: 'error',
                            confirmButtonText: 'Okay'
                        }).then((result) => {
                            this.closeModal();
                        });
                    } else {
                        this.closeModal();
                        this.GetJobs();
                    }

                }).catch(e => {
                    console.log(e);
                });
            },
            StopJob(_jobId) {
                axios.get('JobConfiguration/JobAgent?Id=' + _jobId + "&Action=Stop").then(response => {

                    if (!response.data.Status) {

                        this.showModal = false;

                        Swal.fire({
                            title: 'Error!',
                            text: response.data.Message,
                            type: 'error',
                            confirmButtonText: 'Okay'
                        }).then((result) => {
                            this.closeModal();
                        });
                    } else {

                        this.closeModal();
                        this.GetJobs();
                    }

                }).catch(e => {
                    console.log(e);
                });
            },
            UpdateJob(job) {
                if (this.checkForm()) {
                    var arr = [];

                    for (var key in job) {
                        if (job.hasOwnProperty(key)) {
                            arr.push(key + '=' + job[key]);
                        }
                    };

                    var params = arr.join('&');

                    axios.get('JobConfiguration/UpdateJobs?' + params).then(response => {

                        if (!response.data.Status) {

                            this.showModal = false;

                            Swal.fire({
                                title: 'Error!',
                                text: response.data.Message,
                                type: 'error',
                                confirmButtonText: 'Okay'
                            }).then((result) => {
                                this.closeModal();
                            });
                        } else {

                            this.closeModal();
                            this.GetJobs();
                        }

                    }).catch(e => {
                        console.log(e);
                    });
                }
            },
            getTimeZones() {
                axios.get('DataConfiguration/GetTimeZones').then(response => {
                    this.timeZones = response.data;
                }).catch(e => {
                    console.log(e);
                });
            },
            closeModal() {
                this.job = {
                    Id: '',
                    Cron: '',
                    Queue: '',
                    Class: '',
                    Method: '',
                };
                this.errors = [];
                this.showModal = false;
            },
            OpenModal() {
                this.title = 'Add New Job';
                this.showModal = true;
            },
            checkForm: function (e) {
                this.errors = [];
                if (!this.job.Id) {
                    this.errors.push("Job Id is required.");
                }
                if (!this.job.Cron) {
                    this.errors.push("Cron is required.");
                }
                if (!this.job.Class) {
                    this.errors.push("Class is required.");
                }
                if (!this.job.Method) {
                    this.errors.push("Methodo is required.");
                }
                if (!this.job.Queue) {
                    this.errors.push("Queue is required.");
                }

                if (!this.errors.length) return true;

                if (this.errors.length) return false;

                //e.preventDefault();
            },
            capitalizeString(s) {
                return s.charAt(0).toUpperCase() + s.slice(1);
            },
            getTime(date) {
                return dayjs(date).format('hh:mm:ss A');
            },
            clickCallbackPagination(pageNum) {
                this.pagination.currentPage = Number(pageNum);
            }
        },
        created() {
            this.getTimeZones();
            this.GetJobs();
        },
        computed: {
            getItems: function () {
                let current = this.pagination.currentPage * this.pagination.parPage;
                let start = current - this.pagination.parPage;
                if (this.jobs != null) return this.jobs.slice(start, current);
                else return null;
            },
            getPageCount: function () {
                return Math.ceil(this.jobs.length / this.pagination.parPage);
            }
        }
    });
</script>